package com.mallkit.core.view.controls
{ 
	import flash.display.GradientType;
	import mx.containers.Box;
	import mx.graphics.RectangularDropShadow;
		
	/**
	 *  Colors used to tint the background of the control.
	 *  Pass the same color for both values for a flat-looking control.
	 *  
	 *  @default [ 0xFFFFFF, 0xCCCCCC, 0xFFFFFF, 0xEEEEEE]
	 */
	[Style(name="fillColors", type="Array", arrayType="uint", format="Color", inherit="no")]

	/**
	 *  Alphas used for the background fill of controls. Use [1, 1] to make the control background
	 *  opaque.
	 *  
	 *  @default [ 0.6, 0.4, 0.75, 0.65 ]
	 */
	[Style(name="fillAlphas", type="Array", arrayType="Number", inherit="no")]
	
	
	/**
	 *  An array of color distribution ratios; valid values are from 0 to 255. 
	 *  This value defines the percentage of the width where the color is sampled at 100%
	 *  If fillRations array has different length than fillColors than
	 *  component distributes ratios evenly for all the fillCollors
	 *  
	 *  @default [0, 64, 128, 255]
	 */
	[Style(name="fillRatios", type="Array", arrayType="uint", inherit="no")]
	
	
	/**
	 * Alpha for the border. Ranges from 0.0 to 1
	 * 
	 * @default 1
	 */ 
	[Style(name="borderAlpha", type="Number", inherit="no")]
	
	/**
	 * Alpha for the shadow. Ranges from 0.0 to 1
	 * 
	 * @default .3
	 */ 
	[Style(name="shadowAlpha", type="Number", inherit="no")]
		
	//--------------------------------------
	//  Excluded APIs
	//--------------------------------------
	[Exclude(name="borderSides", kind="style")] // for now borderSides is unsupported, but it is on the wish list
	[Exclude(name="borderStyle", kind="style")]
	
	
	public class GradientBox extends Box
	{	
		private var _fillRotation:Number;
		private var _fillRatios:Array;
		private var _tlRadius:Number;
		private var _trRadius:Number;
		private var _blRadius:Number;
		private var _brRadius:Number;
		
		
		public function GradientBox()
		{
			super();
			
			_fillRotation = 90;
			_tlRadius = 0;
			_trRadius = 0;
			_blRadius = 0;
			_brRadius = 0;
			setStyle("fillRatios", [0, 64, 128, 255]);
			setStyle("fillRotation", 90);
			setStyle("borderAlpha", 1);
			
			// don't use the BorderSkin class, hence don't create it
			// Note: if (border) will always return false
			setStyle("borderStyle", "none");
		}
			
	    override protected function layoutChrome(unscaledWidth:Number, unscaledHeight:Number):void
        {
        	// we don't need to call super because we don't use BorderSkin class
        	// super.layoutChrome(unscaledWidth, unscaledHeight);
        	
			drawBackgroundAndBorder(unscaledWidth, unscaledHeight);
		}
        
        protected function drawBackgroundAndBorder(unscaledWidth:Number, unscaledHeight:Number):void
        {
 			var cornerRadius:Number 	= getStyle("cornerRadius");
			var fillColors:Array 		= getStyle("fillColors");
			var fillAlphas:Array 		= getStyle("fillAlphas");
			var fillRatios:Array		= getStyle("fillRatios");
			var backgroundColor:Number	= getStyle("backgroundColor");
			var borderThickness:Number 	= getStyle("borderThickness");
			var borderColor:int			= getStyle("borderColor");
			var borderAlpha:Number		= getStyle("borderAlpha");
			var dropShadowEnabled:Boolean 	= getStyle("dropShadowEnabled");
			
			if (backgroundColor)
			{
				return;			
			}
			
			if ( fillColors.length > fillAlphas.length)
			{
				throw new Error("fillColors and fillAlphas arrays have to be the same length.");
			}
			
			if ( fillColors.length < fillAlphas.length )
			{
				fillAlphas = fillAlphas.slice(0, fillColors.length);
			}
			
			if (fillColors.length != fillRatios.length)
			{
				fillRatios = [0];
				var ratio:Number;
				var numLoops:int = fillColors.length-1; 
				for (var i:int=1; i<numLoops; i++)
				{
					ratio = i/numLoops;
					fillRatios.push( uint(ratio * 255) );
				}
				fillRatios.push(255);
			}
				
			var fillRadius:Object;
			if (tlRadius || trRadius || blRadius || brRadius)
			{
			 	fillRadius = { tl:tlRadius,
			 				   tr:trRadius,
			 				   bl:blRadius,
			 				   br:brRadius	};
			}
			else
			{
				fillRadius = Math.max(cornerRadius, 0);
			}
			
 			var fill:Object = { x: 0,
								y: 0,
								w: unscaledWidth,
								h: unscaledHeight,
								r: fillRadius };
 
			this.graphics.clear();
			
			if (dropShadowEnabled)
			{
				drawShadow();
			}
			
			if (borderThickness == 0)
			{
				this.graphics.lineStyle(0, 0, 0, true);
			}
			else
			{
				this.graphics.lineStyle(borderThickness, borderColor, borderAlpha, true);
			}
			
			this.drawRoundRect(fill.x, fill.y, fill.w, fill.h, fill.r, fillColors, fillAlphas, fillRotation, GradientType.LINEAR, fillRatios, null);
        }
			
		private function drawShadow():void
	    {
	    	var dropShadowColor:uint 	= getStyle("dropShadowColor");
			var shadowDistance:int 		= getStyle("shadowDistance");
			var shadowDirection:String 	= getStyle("shadowDirection");
			var cornerRadius:Number 	= getStyle("cornerRadius");
			var shadowAlpha:Number 		= getStyle("shadowAlpha");
			
			if (isNaN(shadowAlpha))
			{
				shadowAlpha = .3; //default value for shadow alpha
			}
	    	
	    	var dropShadow:RectangularDropShadow = new RectangularDropShadow();
	    	
	    	//Setting shadow's corners radius
	    	if (tlRadius || trRadius || blRadius || brRadius)
			{
				dropShadow.tlRadius = tlRadius;
				dropShadow.trRadius = trRadius;
 				dropShadow.blRadius = blRadius;
 				dropShadow.brRadius = brRadius;
			}
			else
			{
				//Set all corners(top left and right,and bottom left and right) to cornerRadius value	
				dropShadow.tlRadius = dropShadow.trRadius = dropShadow.blRadius = dropShadow.brRadius = cornerRadius;
			}
			
			//Setting shadow's direction
			switch (shadowDirection)
			{
				case "left":
					dropShadow.angle = 135;
					break;
				case "right":
					dropShadow.angle = 45;
					break;
				case "center":
					dropShadow.angle = 90;
					break;
				default:
					dropShadow.angle = 45;
			}
			
	    	//Setting shadow's distance, color and alpha
	    	dropShadow.distance = shadowDistance;
            dropShadow.color = dropShadowColor;
            dropShadow.alpha = shadowAlpha;
			this.graphics.lineStyle(0, 0, 0, true);
			            
            dropShadow.drawShadow(graphics, 0, 0, unscaledWidth, unscaledHeight);
	    }
	    
	    
	    //----------------------------------
	    //  fillRotation
	    //----------------------------------
	    public function get fillRotation():Number
	    {
	        return _fillRotation;
	    }
	    
	    public function set fillRotation(value:Number):void
	    {
			_fillRotation = value;
			invalidateDisplayList();
	    }
	    
	    //----------------------------------
	    //  tlRadius
	    //----------------------------------
	    public function get tlRadius():Number
	    {
	        return _tlRadius;
	    }
	    
	    public function set tlRadius(value:Number):void
	    {
	    	if (_tlRadius != value)
	    	{
				_tlRadius = value;
				invalidateDisplayList();
			}
	    }
	
	    //----------------------------------
	    //  trRadius
	    //----------------------------------
	    public function get trRadius():Number
	    {
	        return _trRadius;
	    }

	    public function set trRadius(value:Number):void
	    {
	    	if (_trRadius != value)
	    	{
				_trRadius = value;
				invalidateDisplayList();
			}
	    }
	
	    //----------------------------------
	    //  blRadius
	    //----------------------------------
	    public function get blRadius():Number
	    {
	        return _blRadius;
	    }
	
	    public function set blRadius(value:Number):void
	    {
	    	if (_blRadius != value)
	    	{
				_blRadius = value;
				invalidateDisplayList();
			}
	    }
	
	    //----------------------------------
	    //  brRadius
	    //----------------------------------
		public function get brRadius():Number
	    {
	        return _brRadius;
	    }

	    public function set brRadius(value:Number):void
	    {
	    	if (_brRadius != value)
	    	{
				_brRadius = value;
				invalidateDisplayList();
			}
	    }
	    
	}
}